home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1997 November & December / Amiga-CD 1997 #11-12.iso / pd-disketten / ungepackt / 4_96 / apd-4-96-2 / gut gekurvt / pszeichnen.cpp < prev    next >
C/C++ Source or Header  |  1996-03-13  |  8KB  |  186 lines

  1.  
  2. // Bézier-Kurven; (C) C. Marschner, 1996
  3.  
  4. // PsZeichnen:
  5. // Zeichnet nach den Informatinen im Array (s.u.) den Buchstaben "P"
  6. // in verschiedenen Größen 
  7.  
  8. #include <intuition/intuition.h>
  9. #include <graphics/rastport.h>
  10. #include <graphics/gfxmacros.h>
  11. #include <pragma/intuition_lib.h>
  12. #include <pragma/exec_lib.h>
  13. #include <pragma/graphics_lib.h>
  14. #include <pragma/dos_lib.h>
  15. #include <math.h>
  16. #include <stream.h>
  17.  
  18.  
  19. double Bezier(struct RastPort *, double,double,double,double,
  20.                                             double,double,double,double,double,int);
  21.  
  22.  
  23. // Die Daten, um leichter skaliert werden zu können, etwa zwischen 0 u. 1
  24. static double p[][4][2] = { // "P"
  25.     {{ 0.000,0.000},{0.150,0.050},  {0.200,0.050},  {0.250,0.030}},
  26.     {{ 0.250,0.030},{0.300,0.010},  {0.350,0.000},  {0.400,0.000}},
  27.     {{ 0.400,0.000},{0.700,0.000},  {0.775,0.250},  {0.775,0.400}},
  28.     {{ 0.775,0.400},{0.775,0.650},  {0.700,0.700},  {0.450,0.700}},
  29.     {{ 0.450,0.700},{0.350,0.700},  {0.330,0.660},  {0.270,0.660}},
  30.     {{ 0.270,0.660},{0.230,0.660},  {0.200,0.660},  {0.200,0.700}},
  31.     {{ 0.200,0.700},{0.200,0.700},  {0.200,0.950},  {0.200,0.950}},
  32.     {{ 0.200,0.950},{0.180,1.000},  {0.160,1.000},  {0.250,1.030}},
  33.     {{ 0.250,1.030},{0.320,1.045},  {0.340,1.040},  {0.360,1.075}},
  34.     {{ 0.360,1.075},{0.170,1.040},  {0.100,1.030},  {-0.08,1.100}},
  35.     {{ -0.08,1.100},{-0.10,1.050},  {-0.06,1.025},  {0.030,1.025}},
  36.     {{ 0.030,1.025},{0.100,1.010},  {0.100,1.010},  {0.100,0.950}},
  37.     {{ 0.100,0.950},{0.100,0.950},  {0.100,0.200},  {0.100,0.200}},
  38.     {{ 0.100,0.200},{0.100,0.110},  {0.090,0.100},  {0.000,0.100}},
  39.     {{ 0.000,0.100},{0.000,0.010},  {0.000,0.000},  {0.000,0.000}},
  40.         
  41.     {{ 0.200,0.150},{0.210,0.080},  {0.300,0.050},  {0.450,0.050}},
  42.     {{ 0.450,0.050},{0.590,0.050},  {0.650,0.150},  {0.650,0.400}},
  43.     {{ 0.650,0.400},{0.650,0.600},  {0.630,0.650},  {0.450,0.650}},
  44.     {{ 0.450,0.650},{0.400,0.650},  {0.400,0.650},  {0.350,0.630}},
  45.     {{ 0.350,0.630},{0.260,0.605},  {0.300,0.610},  {0.200,0.610}},
  46.     {{ 0.200,0.610},{0.200,0.610},  {0.200,0.150},  {0.200,0.150}},
  47. };
  48.  
  49. /*
  50. struct Screen *scn = OpenScreenTags
  51. (NULL,
  52.     SA_Depth, 2,                                SA_Width, 640,                              
  53.     SA_Height, 523,                         SA_Quiet, TRUE,     
  54.     SA_Type, CUSTOMSCREEN|AUTOSCROLL,   SA_DisplayID, PAL_MONITOR_ID|HIRESLACE_KEY,                 
  55.     SA_Pens, pens,
  56.     TAG_END
  57. );
  58. */
  59.  
  60. struct Window *win =  OpenWindowTags
  61. (NULL, 
  62.             WA_Flags, WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|
  63.                          WFLG_NOCAREREFRESH|WFLG_SIMPLE_REFRESH|
  64.                          WFLG_DEPTHGADGET|WFLG_REPORTMOUSE,
  65.             WA_Top, 11,            WA_Width, 640,
  66.             WA_Height, 512,        WA_Left, 0,
  67.             WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
  68.        /*     WA_CustomScreen, scn, */
  69.             WA_BlockPen, 4, WA_DetailPen, 3,
  70.             WA_Title, (char*)"Bézier-Kurven...",
  71.             TAG_END
  72. );
  73.  
  74. struct RastPort *rp = win->RPort;
  75. int status = 0;
  76.  
  77.  
  78. void main() {
  79.     double k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y;
  80.     int zaehler = 0;
  81.     TmpRas tmpr;
  82.     AreaInfo ai;
  83.  
  84.     if(!win) { CloseWindow(win); return };
  85.     try {
  86.         SetAPen(rp,1);
  87.         // Das Programm benutzt AreaMove/AreaDraw, um den Buchstaben zu füllen.
  88.         // Dazu muß erstmal ein TmpRas besorgt, eine AreaInfo fertiggemacht und
  89.         // das ganze in den RastPort eingetragen werden
  90.  
  91.         // 1. Raster für AreaDraw fertigmachen:
  92.  
  93.         PLANEPTR tr = AllocRaster(640,512);             // anfordern
  94.         if(!tr)                                                 // -> Fehler Nummer drei auswerfen
  95.             throw(3);
  96.         InitTmpRas(&tmpr, tr, RASSIZE(640,512));        // initialisieren
  97.         rp->TmpRas = &tmpr;                                 // und eintragen
  98.         char *buffer = (char*)new WORD[25*5*21+50]; // Puffer für Koordinaten
  99.         InitArea(&ai, buffer, 50*21);                       // AreaInfo-Liste
  100.         AreaInfo *old = rp->AreaInfo;                   // und austauschen
  101.         rp->AreaInfo = &ai;
  102.         BNDRYOFF(rp);                                           // Ausschalten des Rahmen-Pens
  103.  
  104.         // 2. Jetzt kann AreaMove/Draw benutzt werden.
  105.  
  106.         // 6 mal zeichnen
  107.         for(int j = 0; j < 6; j++) {                        
  108.             double range = 0;
  109.             SetAPen(rp,1);  
  110.             // Das äußere vom "P": zwei Reihen a 3 Buchstaben; 6 Größen
  111.             for(int i=0; i<15; i++) 
  112.             {
  113.                 // Die Transformation ist weniger kompliziert, als sie aussieht
  114.                 // Die Figur wird auf 150 Punkt gestreckt, wobei bei jedem weiteren
  115.                 // "P" die Figur um 15 Pkt. größer wird. Schließlich wird noch der
  116.                 // Nullpunkt verschoben, wobei ab j=3 eine zweite Zeile aufgemacht wird
  117.                 k1x = p[i][0][0]    * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
  118.                 k1y = p[i][0][1]    * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
  119.                 k2x = p[i][1][0]    * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3); 
  120.                 k2y = p[i][1][1]    * (120.0+ 20*j) + 50.0 + 190.0 * (j>2); 
  121.                 k3x = p[i][2][0]    * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3); 
  122.                 k3y = p[i][2][1]    * (120.0+ 20*j) + 50.0 + 190.0 * (j>2); 
  123.                 k4x = p[i][3][0]    * (120.0+ 20*j) + 50.0 + 160.0 * (j<3?j:j-3);
  124.                 k4y = p[i][3][1]    * (120.0+ 20*j) + 50.0 + 190.0 * (j>2);
  125.                 if(!i) AreaMove(rp,(long)k1x,(long)k1y);
  126.                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,0,0);
  127.             }
  128.             AreaEnd(rp);
  129.             SetAPen(rp,0);
  130.             for(i=15; i<21; i++) {
  131.                 k1x = p[i][0][0]    * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
  132.                 k1y = p[i][0][1]    * (120.0+20*j) + 50.0 + 190.0 * (j>2);
  133.                 k2x = p[i][1][0]    * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3); 
  134.                 k2y = p[i][1][1]    * (120.0+20*j) + 50.0 + 190.0 * (j>2); 
  135.                 k3x = p[i][2][0]    * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3); 
  136.                 k3y = p[i][2][1]    * (120.0+20*j) + 50.0 + 190.0 * (j>2); 
  137.                 k4x = p[i][3][0]    * (120.0+20*j) + 50.0 + 160.0 * (j<3?j:j-3);
  138.                 k4y = p[i][3][1]    * (120.0+20*j) + 50.0 + 190.0 * (j>2);
  139.                 if(i==15) AreaMove(rp,(long)k1x,(long)k1y);
  140.                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,0,0);
  141.             }
  142.             AreaEnd(rp);
  143.             
  144.         }
  145.         Delay(250);             // 5 Sekunden warten
  146.  
  147.         // 3. alte Werte wieder zurückschreiben:
  148.  
  149.         delete buffer;
  150.         rp->AreaInfo = old;
  151.         rp->TmpRas = 0;
  152.         FreeRaster(tr,640,512);     
  153.     } catch(int n) { 
  154.         if(n>1) cout << "Fehler "<< n << "\n";
  155.     }
  156.     CloseWindow(win);
  157. }
  158.  
  159.  
  160. double Bezier(struct RastPort *rp, 
  161.     double k0x,double k0y,double k1x,double k1y,
  162.     double k2x,double k2y,double k3x,double k3y, double nr,int flag) 
  163. {
  164.     double bx, by, emt, emt2, t2, tm3, emtm3;
  165.  
  166.     // improvisierte Abschätzung der Schrittweite:
  167.     const double range = 
  168.         floor(10+(fabs(k0y-k1y)+fabs(k0x-k1x)+fabs(k1x-k2x)+
  169.                         fabs(k1y-k2y)+fabs(k2x-k3x)+fabs(k2y-k3y))/30.0);
  170.     const double step = 1.0/range;
  171.     const double rst = range*step;  // Konstante z. schnelleren Bearbeiten
  172.     
  173.     AreaDraw(rp,(long)k0x,(long)k0y);
  174.     
  175.     for(double t = step; t <= rst; t+= step) 
  176.     {
  177.         emt = 1-t; emt2=emt*emt; t2=t*t; tm3=3*t; emtm3 = 3*emt;
  178.         bx = emt2*(emt*k0x + tm3*k1x) + t2*(emtm3*k2x + t*k3x);
  179.         by = emt2*(emt*k0y + tm3*k1y) + t2*(emtm3*k2y + t*k3y);
  180.         AreaDraw(rp,(long)bx,(long)by);
  181.     }
  182.     
  183.     return range;
  184. }
  185.  
  186.